using System;
using System.Linq.Expressions;
using System.Reflection;
namespace ServiceStack.Reflection
{
	public static class StaticAccessors<TEntity>
	{
		public static Func<TEntity, TId> TypedGetPropertyFn<TId>(PropertyInfo pi)
		{
			return (Func<TEntity, TId>)pi.GetMethodInfo(true).MakeDelegate(typeof(Func<TEntity, TId>), true);
		}
		public static Func<TEntity, object> ValueUnTypedGetPropertyFn<TId>(PropertyInfo pi)
		{
			Func<TEntity, TId> typedPropertyFn = StaticAccessors<TEntity>.TypedGetPropertyFn<TId>(pi);
			return (TEntity x) => typedPropertyFn(x);
		}
		public static Func<TEntity, object> ValueUnTypedGetPropertyTypeFn(PropertyInfo pi)
		{
			MethodInfo method = ((Delegate)typeof(StaticAccessors<TEntity>).GetMethodInfo("TypedGetPropertyFn", null).MakeGenericMethod(new Type[]
			{
				pi.PropertyType
			}).Invoke(null, new PropertyInfo[]
			{
				pi
			})).Method;
			ParameterExpression parameterExpression;
			return Expression.Lambda<Func<TEntity, object>>(Expression.Convert(Expression.Call(Expression.Convert(parameterExpression, method.DeclaringType), method), typeof(object)), new ParameterExpression[]
			{
				parameterExpression
			}).Compile();
		}
		public static Func<object, object> UnTypedGetPropertyFn<TId>(PropertyInfo pi)
		{
			Func<TEntity, TId> typedPropertyFn = StaticAccessors<TEntity>.TypedGetPropertyFn<TId>(pi);
			return (object x) => typedPropertyFn((TEntity)((object)x));
		}
		public static Action<TEntity, TId> TypedSetPropertyFn<TId>(PropertyInfo pi)
		{
			return (Action<TEntity, TId>)pi.SetMethod(true).MakeDelegate(typeof(Action<TEntity, TId>), true);
		}
		public static Action<TEntity, object> ValueUnTypedSetPropertyFn<TId>(PropertyInfo pi)
		{
			Action<TEntity, TId> typedPropertyFn = StaticAccessors<TEntity>.TypedSetPropertyFn<TId>(pi);
			return delegate(TEntity x, object y)
			{
				typedPropertyFn(x, (TId)((object)y));
			};
		}
		public static Action<TEntity, object> ValueUnTypedSetPropertyTypeFn(PropertyInfo pi)
		{
			MethodInfo method = ((Delegate)typeof(StaticAccessors<TEntity>).GetMethodInfo("TypedSetPropertyFn", null).MakeGenericMethod(new Type[]
			{
				pi.PropertyType
			}).Invoke(null, new PropertyInfo[]
			{
				pi
			})).Method;
			ParameterExpression parameterExpression;
			ParameterExpression parameterExpression2;
			return Expression.Lambda<Action<TEntity, object>>(Expression.Call(Expression.Convert(parameterExpression, method.DeclaringType), method, new Expression[]
			{
				Expression.Convert(parameterExpression2, pi.PropertyType)
			}), new ParameterExpression[]
			{
				parameterExpression,
				parameterExpression2
			}).Compile();
		}
		public static Action<object, object> UnTypedSetPropertyFn<TId>(PropertyInfo pi)
		{
			Action<TEntity, TId> typedPropertyFn = StaticAccessors<TEntity>.TypedSetPropertyFn<TId>(pi);
			return delegate(object x, object y)
			{
				typedPropertyFn((TEntity)((object)x), (TId)((object)y));
			};
		}
	}
}
